import { Row, Col, Affix, Spin, BackTop, message, Empty } from 'antd';
import { DislikeOutlined, LikeOutlined } from '@ant-design/icons'
import * as React from 'react';
import { RouteComponentProps } from 'react-router-dom'
import markdownIt from 'markdown-it'
import Navbar from 'markdown-navbar';
import PubSub from 'pubsub-js';
import hljs from 'highlight.js'
import moment from 'moment'
import { reqArticle, reqIncrease } from '../../axios';
// import 'highlight.js/styles/atelier-forest-dark.css'
import './ArticleDetail.less'
import 'markdown-navbar/dist/navbar.css'
import MyComment from '../../components/Comment/MyComment';
import MyChildComment from '../../components/Comment/MyChildComment';
import CommentText from '../../components/CommentText/CommentText';


export interface ArticleDetailProps extends RouteComponentProps {

}
interface articleDetail {
    article: {
        id: number
        read: number
        createTime: string
        title: string
        content: string
        cover: string
        support: number
        oppose: number
    }, comments: comment[]
}
interface comment {
    id: number
    articleId: number
    createTime: string
    reviewerName: string
    parentId: number
    reviewerEmail: string
    content: string
    reply: comment[]
}
export interface ArticleDetailState {
    articleDetil: articleDetail
    loading: Boolean
    commentCount: number
}

class ArticleDetail extends React.PureComponent<ArticleDetailProps, ArticleDetailState> {
    commentsArray = []
    state = {
        loading: true,
        articleDetil: {
            article: {
                id: 0,
                read: 0,
                createTime: '',
                title: '',
                content: '',
                cover: '',
                support: 0,
                oppose: 0,
            },
            comments: [
                {
                    id: 0,
                    articleId: 0,
                    createTime: '',
                    reviewerName: '',
                    parentId: 0,
                    reviewerEmail: '',
                    content: '',
                    reply: []
                }
            ]
        },
        commentCount: 0
    }
    async componentDidMount() {
        //订阅 添加评论 
        PubSub.subscribe('comment', this.updateComments)
        //@ts-ignore
        const { id } = this.props.match.params;
        try {
            //根据id获取文章
            const response = await reqArticle(id);
            if (response.data.success) {
                this.setState({ articleDetil: response.data.data }, () => {
                    this.commentsSort();
                    this.getCommentCount(this.state.articleDetil.comments);
                });
                this.setState({ loading: false })
                //@ts-ignore 
                this.refs.loading.setAttribute('style', `display:none`)
                //阅读量+1 { articleId: id, count: 1, filedName: 'read' }
                this.updateCount(id, 1, 'read');
            }
        } catch (error) {
            console.log(error);
        }
    }
    //增加阅读量 点赞 踩
    updateCount = async (articleId: number, count: number, filedName: string) => {
        const response = await reqIncrease(`filedName=${filedName}&articleId=${articleId}&count=${count}`);
        if (response.data.success) {
            if (filedName === 'support') {
                message.success('感谢你的点赞 O(∩_∩)O哈哈~')
            } else if (filedName === 'oppose') {
                message.success('讨厌(〝▼皿▼)')
            } else {
                message.success('欢迎阅读');
            }
        } else {
            message.error(response.data.message);
        }
    }

    //遍历评论列表
    getCommentList = (comments: comment[]) => {
        return comments.map(comment => {
            if (comment.reply && comment.reply.length > 0) {
                return (
                    <MyComment createTime={comment.createTime} parentId={comment.parentId} articleId={this.state.articleDetil.article.id} key={comment.id} id={comment.id} author={comment.reviewerName} content={comment.content}>
                        {
                            // this.getCommentList(comment.reply || [])
                            comment.reply.map(c => {
                                return (<MyChildComment createTime={c.createTime} parentId={c.parentId} articleId={this.state.articleDetil.article.id} key={c.id} id={c.id} author={c.reviewerName} content={c.content}></MyChildComment>)
                            })
                        }
                    </MyComment>
                )
            } else {
                return (<MyComment createTime={comment.createTime} parentId={comment.parentId} articleId={this.state.articleDetil.article.id} key={comment.id} id={comment.id} author={comment.reviewerName} content={comment.content}></MyComment>
                )
            }
        })

    }
    //修改评论列表 增加评论后同步修改页面内的数据
    updateComments = async (_: string, comment: comment) => {
        this.setState((state) => {
            if (comment.parentId === null) {
                return {
                    articleDetil: {
                        article: state.articleDetil.article,
                        comments: [comment, ...state.articleDetil.comments]
                    }
                }
            } else {
                return {
                    articleDetil: {
                        article: state.articleDetil.article,
                        comments: state.articleDetil.comments.map(c => {
                            if (c.id === comment.parentId) {
                                return {
                                    ...c,
                                    reply: [comment, ...c.reply||[]]
                                }
                            } else {
                                return {
                                    ...c
                                }
                            }
                        })
                    }
                }
            }
        })
        //修改评论数
        this.getCommentCount(this.state.articleDetil.comments);
    }
    //根据评论的时间排序
    commentsSort = () => {
        this.setState((state) => ({
            ...state,
            articleDetil: {
                article: state.articleDetil.article,
                comments: state.articleDetil.comments.sort((a: comment, b: comment) => {
                    return moment(b.createTime).unix() - moment(a.createTime).unix();
                })
            }
        }))
    }
    //计算评论的数量
    getCommentCount = (comments: comment[]) => {
        const commentCount = comments.reduce((pre: number, comment: comment) => {
            const length = comment.reply === null ? 0 : comment.reply.length;
            if (length > 0) {
                pre = pre + length;
            }
            return ++pre
        }, 0);
        this.setState({ commentCount })
    }
    //用户点击 赞 踩
    handleEvaluate = (status: string) => {
        //@ts-ignore
        const { id } = this.props.match.params;
        this.updateCount(id, 1, status);
        this.setState((state: ArticleDetailState) => {
            return {
                ...state,
                articleDetil: {
                    comments: state.articleDetil.comments,
                    article: {
                        ...state.articleDetil.article,
                        //@ts-ignore
                        [status]: state.articleDetil.article[status] + 1
                    }
                }
            }
        })
    }
    render() {      
        const { articleDetil, loading, commentCount } = this.state;
        const md: any = markdownIt({
            html: true,
            highlight: function (str, lang) {
                // 此处判断是否有添加代码语言
                if (lang && hljs.getLanguage(lang)) {
                    try {
                        // 得到经过highlight.js之后的html代码
                        const preCode = hljs.highlight(lang, str, true).value
                        // 以换行进行分割
                        const lines = preCode.split(/\n/).slice(0, -1)
                        // 添加自定义行号
                        let html = lines.map((item, index) => {
                            return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' + item + '</li>'
                        }).join('')
                        html = '<ol>' + html + '</ol>'
                        // 添加代码语言
                        if (lines.length) {
                            html += '<b class="name">' + lang + '</b>'
                        }
                        return '<pre class="hljs"><code>' +
                            html +
                            '</code></pre>'
                    } catch (__) { }
                }
                // 未添加代码语言，此处与上面同理
                const preCode = md.utils.escapeHtml(str)
                const lines = preCode.split(/\n/).slice(0, -1)
                let html = lines.map((item: any, index: any) => {
                    return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' + item + '</li>'
                }).join('')
                html = '<ol>' + html + '</ol>'
                return '<pre class="hljs"><code>' +
                    html +
                    '</code></pre>'
            }
        })
        const markdown = articleDetil.article.content;
        const imgUrl = articleDetil.article.cover;
        const title = articleDetil.article.title;
        const time = articleDetil.article.createTime;
        const support = articleDetil.article.support;
        const oppose = articleDetil.article.oppose;
        const read = articleDetil.article.read;
        const html = md.render(markdown);
        const style = {
            height: 40,
            width: 40,
            lineHeight: '40px',
            borderRadius: 4,
            backgroundColor: '#1088e9',
            color: '#fff',
            textAlign: 'center',
            fontSize: 14,
        };
        return (

            <>
                <div className='detail'>

                    <div ref='loading' className='loading'>
                        <Spin size="large" spinning={loading} />
                    </div>
                    <div className='detail-banner'>
                        <div className='detail-banner-border'>
                            <div className='detail-banner-img' style={{ backgroundImage: `url(${imgUrl})` }}></div>
                        </div>
                        <div className='detail-banner-little-img-box'>
                            <div className='detail-banner-little-img' style={{ backgroundImage: `url(${imgUrl})` }}></div>
                        </div>
                    </div>
                    <div className='detail-title'>
                        <h1>{title}</h1>
                    </div>
                    <div className='detail-message'>
                        <span className='detail-time'>发布日期：{moment(time).format('YYYY年MM月DD日')}</span>
                        <span className='hr'></span>
                        <span className='detail-readCount'>阅读量：{read}</span>
                        <span className='hr'></span>
                        <span className='good'>点赞：{support}</span>
                        <span className='hr'></span>
                        <span className='good'>反对：{oppose}</span>
                    </div>
                    <div className='detail-hr'></div>
                    <Row justify='center'>
                        <Col className='detail-left' xs={24} sm={24} md={24} lg={18} xl={19}>
                            <Affix offsetTop={50}>
                                <div className='article-support'>
                                    <div className='good' style={{ backgroundColor: '#f44355' }} onClick={() => this.handleEvaluate('support')}><LikeOutlined /></div>
                                    <div className='no-good' style={{backgroundColor:'#007bff'}} onClick={() => this.handleEvaluate('oppose')}><DislikeOutlined /></div>
                                </div>
                            </Affix>
                            <div className='detail-content' dangerouslySetInnerHTML={{ __html: html }}></div>
                            <div className='article-end'></div>
                            <div className='article-comment'>
                                <div className='article-edit'>
                                    <h3>文章看完了，发表一下看法吧！</h3>
                                    <CommentText articleId={articleDetil.article.id} id={null}></CommentText>
                                </div>
                                <div className='comment-title'>
                                    评论列表 ({commentCount}条评论)
                                </div>
                                {commentCount===0?<Empty></Empty>:this.getCommentList(articleDetil.comments)}
                            </div>
                        </Col>
                        <Col className='detail-right'  xs={0} sm={0} md={0} lg={5} xl={5}>
                            <Affix className='detail-catalog'>
                                <div className='article-nav'>
                                    <div className='detail-catalog-title'>
                                        文章目录
                                    </div>
                                    <Navbar
                                        className='markdownNav'
                                        source={markdown}
                                        ordered={false}
                                        headingTopOffset={10}
                                    />
                                </div>
                            </Affix>
                        </Col>
                    </Row>
                </div>
                <BackTop>
                    {/* @ts-ignore */}
                    <div style={style}>
                        TOP
                    </div>
                </BackTop>
            </>
        );
    }
}

export default ArticleDetail;